package com.smallnico.opencv;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Rect;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import com.alibaba.fastjson.JSON;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;


public class Test4 {

	public static void main(String[] args) {
		System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
		String originalImgPath = "C:\\Users\\ainil\\Desktop\\1.png";
		Mat src = Imgcodecs.imread(originalImgPath);
		imgCorrection(src);
	}
	
	public static void imgCorrection(Mat srcImage) {
		Mat binary = ImgBinarization(srcImage);
		Imgcodecs.imwrite("C:\\\\Users\\\\ainil\\\\Desktop\\\\2.png", binary);
		Mat preprocess = preprocess(binary);
		Imgcodecs.imwrite("C:\\\\Users\\\\ainil\\\\Desktop\\\\3.png", preprocess);
	    List<Rect> rects = findTextRegion(preprocess) ;
	    output(rects,srcImage);
	}
	
	public static Mat ImgBinarization(Mat srcImage){
        Mat gray_image = null;
        try {
        	gray_image = new Mat(srcImage.height(), srcImage.width(), CvType.CV_8UC1);
        	Imgproc.cvtColor(srcImage,gray_image,Imgproc.COLOR_RGB2GRAY);
		} catch (Exception e) {
			gray_image = srcImage.clone();
			gray_image.convertTo(gray_image, CvType.CV_8UC1);
			System.out.println("原文异常，已处理...");
		}
        Mat thresh_image = new Mat(srcImage.height(), srcImage.width(), CvType.CV_8UC1);
        Imgproc.threshold(gray_image, thresh_image,100, 255, Imgproc.THRESH_BINARY);
		return thresh_image;
	}
	
	/**
	 * 根据二值化图片进行膨胀与腐蚀
	 * @author MaChao
	 * @time 2019-9-29
	 */
	public static Mat preprocess(Mat binary){
	    Mat element1 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(20, 4));
	    Mat element2 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(1, 1));
	    Mat dilate1 = new Mat();
	    Imgproc.dilate(binary, dilate1, element2);
	    
	    Mat erode1 = new Mat();
	    Imgproc.erode(dilate1, erode1, element1);
	    Mat dilate2 = new Mat();
	    Imgproc.dilate(erode1, dilate2, element2);
	    return dilate2;
	}
	
	 public static List<Rect> findTextRegion(Mat img)
	    {
	    	List<Rect> rects = new ArrayList<Rect>();
	        //1.查找轮廓
	    	List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
	    	Mat hierarchy = new Mat();
			Imgproc.findContours(img, contours, hierarchy, Imgproc.RETR_CCOMP, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));
			
	        int img_width = img.width();
	        int img_height = img.height();
	        int size = contours.size();
	        for (int i = 0; i < size; i++) {
	        	double area = Imgproc.contourArea(contours.get(i));
		        if (area < 500)
		            continue;
	            //轮廓近似，作用较小，approxPolyDP函数有待研究
	            double epsilon = 0.001*Imgproc.arcLength(new MatOfPoint2f(contours.get(i).toArray()), true);
	            MatOfPoint2f approxCurve = new MatOfPoint2f();
	            Imgproc.approxPolyDP(new MatOfPoint2f(contours.get(i).toArray()), approxCurve, epsilon, true);
	     
	            //找到最小矩形，该矩形可能有方向
	            RotatedRect rect = Imgproc.minAreaRect(new MatOfPoint2f(contours.get(i).toArray()));
	            //计算高和宽
	            int m_width = rect.boundingRect().width;
	            int m_height = rect.boundingRect().height;
	     
	            //筛选那些太细的矩形，留下扁的
	            if (m_width < m_height)
	                continue;
	            if(img_width == rect.boundingRect().br().x)
	            	continue;
	            if(img_height == rect.boundingRect().br().y)
	            	continue;
	        	
	        	Rect rec = Imgproc.boundingRect(contours.get(i));
	        	rects.add(rec);
			}
	        return rects;
	    }
	 
	 private static void cvWhite(Mat dst) {
			int num=0;
			int num_rows = dst.rows();
			int num_col = dst.cols();
			for (int i = 0; i < num_rows; i++) {
				for (int j = 0; j < num_col; j++) {
					// 获取每个像素
					double[] clone = dst.get(i, j).clone();
					double hun = clone[0]; // HSV hun
					
					if (hun > 240) {
						if (clone[1] > 240) {
							if (clone[2] > 240) {
								// 红色范围,全部设置为黑色,
								clone[0] = 149;
								clone[1] = 236;
								clone[2] = 105;
								num++;
								dst.put(i, j, clone);
							}
						}
					}
					
				}
			}
		}
	 
	 public static List<Object> output(List<Rect> rects,Mat srcImage) {
	    	for(int i = 0; i < rects.size();i++){
	    		Rect rec = rects.get(i);
	    		Mat newMat = srcImage.colRange(rec.x, rec.x + rec.width).rowRange(rec.y, rec.y + rec.height);
	    		
	    		String path = "C:\\Users\\ainil\\Desktop\\opencv-test\\" + i + ".jpg";
	    		
	    		Imgcodecs.imwrite(path, newMat);
	    		
	    		Map<String, Object> requestBody = new HashMap<>();
	    		requestBody.put("filePath", path);
	    		
	    		String resp = HttpUtil.post("http://127.0.0.1:8888", JSONUtil.toJsonStr(requestBody));
	    		Resp body = JSON.parseObject(resp, Resp.class);
	    		
	    		StringBuilder builder = new StringBuilder();
	    		for(List<String> list: body.getData()) {
	    			builder.append(StringUtils.join(list.toArray(), ""));
	    		}
	    		System.out.println(JSON.toJSONString(rec));
	    		System.out.println(builder);
		    }
	    	return null;
		}
}
